package web

import (
	"net/http"

	"gitee.com/zhyclouds/fable-scribe/internal/service"
	"gitee.com/zhyclouds/fable-scribe/internal/web/jwt"
	"gitee.com/zhyclouds/fable-scribe/pkg/ginx"
	"gitee.com/zhyclouds/fable-scribe/pkg/logger"
	"github.com/dlclark/regexp2"
	"github.com/gin-gonic/gin"
)

const (
	passwordRegexPattern = `^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$`
)

// UserHandler 用户控制器
type UserHandler struct {
	userService service.UserService
	jwtHandler  jwt.Handler
	l           logger.Logger

	regex *regexp2.Regexp
}

// NewUserHandler 创建用户控制器实例
func NewUserHandler(userService service.UserService, jwtHandler jwt.Handler, l logger.Logger) *UserHandler {
	passwordRegex, _ := regexp2.Compile(passwordRegexPattern, regexp2.None)

	return &UserHandler{
		userService: userService,
		jwtHandler:  jwtHandler,
		l:           l,

		regex: passwordRegex,
	}
}

func (h *UserHandler) Register(ctx *gin.Context, req RegisterReq) (ginx.Result, error) {
	// 1. 验证两次密码是否一致
	if req.Password != req.ConfirmPassword {
		return ginx.Result{
			Code: 4,
			Msg:  "两次输入的密码不一致",
		}, nil
	}

	// 2. 验证密码格式是否符合要求
	matched, _ := h.regex.MatchString(req.Password)
	if !matched {
		return ginx.Result{
			Code: 4,
			Msg:  "密码必须包含字母、数字、特殊字符，并且不少于八位",
		}, nil
	}

	// 调用服务层注册用户
	user, err := h.userService.Register(ctx, req.Username, req.Password)
	if err == service.ErrDuplicateUsername {
		return ginx.Result{
			Code: 4,
			Msg:  "用户已存在",
		}, nil
	}

	if err != nil {
		h.l.Error("注册用户失败",
			logger.String("error", err.Error()),
			logger.String("username", req.Username))
		return ginx.Result{
			Code: 5,
			Msg:  "系统错误",
		}, nil
	}

	// 注册成功后生成JWT token
	if err := h.jwtHandler.SetLoginToken(ctx, user.ID); err != nil {
		h.l.Error("生成 token 失败",
			logger.String("error", err.Error()),
			logger.Int64("userid", user.ID))
		return ginx.Result{
			Code: 5,
			Msg:  "系统错误",
		}, nil
	}

	// 返回成功响应
	return ginx.Result{
		Msg: "ok",
		Data: map[string]interface{}{
			"nickname": user.Nickname,
		},
	}, nil
}

func (h *UserHandler) Login(ctx *gin.Context, req LoginReq) (ginx.Result, error) {
	user, err := h.userService.Login(ctx, req.Username, req.Password)
	if err == service.ErrInvalidUsernameOrPassword {
		return ginx.Result{
			Code: 4,
			Msg:  "用户不存在或密码不对",
		}, nil
	}

	if err != nil {
		h.l.Error("用户登录失败",
			logger.String("error", err.Error()),
			logger.String("username", req.Username))
		return ginx.Result{
			Code: 5,
			Msg:  "系统错误",
		}, nil
	}

	// 登录成功后生成JWT token
	if err := h.jwtHandler.SetLoginToken(ctx, user.ID); err != nil {
		h.l.Error("生成token 失败",
			logger.String("error", err.Error()),
			logger.Int64("userid", user.ID))
		return ginx.Result{
			Code: 5,
			Msg:  "系统错误",
		}, nil
	}

	return ginx.Result{
		Code: 0,
		Msg:  "ok",
		Data: map[string]interface{}{
			"nickname": user.Nickname,
		},
	}, nil
}

func (h *UserHandler) Logout(ctx *gin.Context) {
	err := h.jwtHandler.ClearToken(ctx)
	if err != nil {
		ctx.JSON(http.StatusOK, ginx.Result{
			Code: 5,
			Msg:  "系统错误",
		})
		return
	}

	ctx.JSON(http.StatusOK, ginx.Result{
		Msg: "ok",
	})
}

// RegisterRoutes 注册路由
func (h *UserHandler) RegisterRoutes(server *gin.Engine) {
	userGroup := server.Group("/user")
	{
		userGroup.POST("/register", ginx.WrapBody[RegisterReq](h.Register))
		userGroup.POST("/login", ginx.WrapBody[LoginReq](h.Login))
		userGroup.POST("/logout", h.Logout)
	}
}
